package com.zzy.test;


import java.util.Hashtable;
import java.util.Properties;

import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.*;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;

/**
 * @author moonxy
 * @Description:对AD域用户的增删改查操作
 * @date 2018-05-15
 */
public class ADUserUtils {
    DirContext dc = null;
    String root = "OU=软件研发部,DC=zxf,DC=com";
// LDAP的根节点的DC

    /**
     * @Description:程序入口
     * @author moonxy
     * @date 2018-05-15
     */
    public static void main(String[] args) {
        ADUserUtils utils = new ADUserUtils();

        utils.add("JimGreen");
        //utils.searchInformation(utils.root);

        //utils.updatePWD("");
        // SearchResult sr = utils.searchByUserName(utils.root, "JimGreen");
        //System.out.println(sr.getName());
//
//        utils.modifyInformation(sr.getName(), "M1380005");

//        utils.searchInformation(utils.root);

//        utils.renameEntry("CN=JimGreen,OU=Java开发组,OU=软件研发部,DC=moonxy,DC=com", "CN=JimGreen,OU=Web前端组,OU=软件研发部,DC=moonxy,DC=com");

//        utils.delete("CN=JimGreen,OU=Web前端组,OU=软件研发部,DC=moonxy,DC=com");

        utils.close();
    }

    /**
     * 初始化
     */
    public ADUserUtils() {
        super();
        init();
    }

    /**
     * @Description:初始化AD域服务连接
     * @author moonxy
     * @date 2018-05-15
     */
    public void init() {
        Properties env = new Properties();
        String adminName = "administrator@zxf.com";//username@domain
        String adminPassword = "!123456a";//password
        String ldapURL = "LDAP://192.168.219.143:389";//ip:port
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.SECURITY_AUTHENTICATION, "simple");//LDAP访问安全级别："none","simple","strong"
        env.put(Context.SECURITY_PRINCIPAL, adminName);
        env.put(Context.SECURITY_CREDENTIALS, adminPassword);
        env.put(Context.PROVIDER_URL, ldapURL);
        try {
            dc = new InitialLdapContext(env, null);
            System.out.println("AD域服务连接认证成功");
        } catch (Exception e) {
            System.out.println("AD域服务连接认证失败");
            e.printStackTrace();
        }
    }

    /**
     * @Description:关闭AD域服务连接
     * @author moonxy
     * @date 2018-05-15
     */
    public void close() {
        if (dc != null) {
            try {
                dc.close();
            } catch (NamingException e) {
                System.out.println("NamingException in close():" + e);
            }
        }
    }

    /**
     * @Description:新增AD域用户
     * @author moonxy
     * @date 2018-05-15
     */
    public void add(String newUserName) {
        try {
            Attributes attrs = new BasicAttributes(true);
            attrs.put("objectClass", "user");
            attrs.put("samAccountName", newUserName);
            attrs.put("displayName", newUserName);
            attrs.put("userPrincipalName", newUserName + "@zxf.com");

//            byte[] psd =  "!147258a".getBytes("UTF-16LE");
//            attrs.put("unicodePwd", psd);

            dc.createSubcontext("CN=" + newUserName + "," + root, attrs);
            System.out.println("新增AD域用户成功:" + newUserName);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("新增AD域用户失败:" + newUserName);
        }
    }

    /**
     * @Description:删除AD域用户
     * @author moonxy
     * @date 2018-05-15
     */
    public void delete(String dn) {
        try {
            dc.destroySubcontext(dn);
            System.out.println("删除AD域用户成功:" + dn);
        } catch (Exception e) {
            System.out.println("删除AD域用户失败:" + dn);
            e.printStackTrace();
        }
    }

    /**
     * @Description:重命名AD域用户
     * @author moonxy
     * @date 2018-05-15
     */
    public boolean renameEntry(String oldDN, String newDN) {
        try {
            dc.rename(oldDN, newDN);
            System.out.println("重命名AD域用户成功");
            return true;
        } catch (NamingException ne) {
            System.out.println("重命名AD域用户失败");
            ne.printStackTrace();
            return false;
        }
    }

    /**
     * @Description:修改AD域用户属性
     * @author moonxy
     * @date 2018-05-15
     */
    public boolean modifyInformation(String dn, String fieldValue) {
        try {
            ModificationItem[] mods = new ModificationItem[1];
            // 修改属性
            Attribute attr0 = new BasicAttribute("homePhone", fieldValue);
            //mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr0);//新增属性
            //mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE,attr0);//删除属性
            mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr0);//覆盖属性
            dc.modifyAttributes(dn + "," + root, mods);
            System.out.println("修改AD域用户属性成功");
            return true;
        } catch (Exception e) {
            System.err.println("修改AD域用户属性失败");
            e.printStackTrace();
            return false;
        }
    }

    /**
     * @Description:搜索指定节点下的所有AD域用户
     * @author moonxy
     * @date 2018-05-15
     */
    public void searchInformation(String searchBase) {
        try {
            SearchControls searchCtls = new SearchControls();
            searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            String searchFilter = "objectClass=user";
            String returnedAtts[] = {"memberOf"};
            searchCtls.setReturningAttributes(returnedAtts);
            NamingEnumeration<SearchResult> answer = dc.search(searchBase, searchFilter, searchCtls);
            while (answer.hasMoreElements()) {
                SearchResult sr = (SearchResult) answer.next();
                System.out.println("<<<::[" + sr.getName() + "]::>>>>");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description:指定搜索节点搜索指定域用户
     * @author moonxy
     * @date 2018-05-15
     */
    public SearchResult searchByUserName(String searchBase, String userName) {
        SearchControls searchCtls = new SearchControls();
        searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        String searchFilter = "sAMAccountName=" + userName;
        String returnedAtts[] = {"memberOf"}; //定制返回属性
        searchCtls.setReturningAttributes(returnedAtts); //设置返回属性集
        try {
            NamingEnumeration<SearchResult> answer = dc.search(searchBase, searchFilter, searchCtls);
            return answer.next();
        } catch (Exception e) {
            System.err.println("指定搜索节点搜索指定域用户失败");
            e.printStackTrace();
        }
        return null;
    }



    /**
     * 使用java连接AD域，验证 用户名字和密码是否匹配
     * @author Herman.Xiong
     * @date 2014-12-23 下午02:24:04
     * @return void
     * @param username 用户名
     * @param password 密码
     *   // connect("zhangsan@zxf.com", "!258369a");
     */
    public static void connect(String username,String password) {
        DirContext ctx=null;
        Hashtable<String,String> HashEnv = new Hashtable<String,String>();
        HashEnv.put(Context.SECURITY_AUTHENTICATION, "simple"); // LDAP访问安全级别(none,simple,strong)
        HashEnv.put(Context.SECURITY_PRINCIPAL, username); //AD的用户名
        HashEnv.put(Context.SECURITY_CREDENTIALS, password); //AD的密码
        HashEnv.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory"); // LDAP工厂类
        HashEnv.put("com.sun.jndi.ldap.connect.timeout", "3000");//连接超时设置为3秒
        HashEnv.put(Context.PROVIDER_URL, "LDAP://192.168.219.143:389");// 默认端口389
        try {
            ctx = new InitialDirContext(HashEnv);// 初始化上下文
            System.out.println("身份验证成功!");
        } catch (AuthenticationException e) {
            System.out.println("身份验证失败!");
            e.printStackTrace();
        } catch (javax.naming.CommunicationException e) {
            System.out.println("AD域连接失败!");
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("身份验证未知异常!");
            e.printStackTrace();
        } finally{
            if(null!=ctx){
                try {
                    ctx.close();
                    ctx=null;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * @Description:修改AD域用户密码
     * @author zhuyr
     * @date 2018-07-03
     */
    public void updatePWD(String dn) {
        String sOldPassword ="!258369a";
        String newQuotedPassword = "!147258a";
        try {
            byte[] oldUnicodePassword = sOldPassword.getBytes("UTF-16LE");
            byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
            ModificationItem[] mods = new ModificationItem[2];
           // mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("unicodePwd", newUnicodePassword));
           mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, new BasicAttribute("unicodePwd", oldUnicodePassword));  //userPassword
            mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("unicodePwd", newUnicodePassword));
            dc.modifyAttributes("CN=tzzy,OU=软件研发部,DC=zxf,DC=com", mods);
            System.out.println("修改密码成功！");
        }catch(Exception e) {
            e.printStackTrace();
        }
    }

}
